import event from "../../utils/event";
import { _decorator, Component, Node, EventTouch, Vec2, UITransform, input, Input, EventKeyboard, KeyCode } from "cc";
const { ccclass, property } = _decorator;

@ccclass("Game/UI/Rocker")
export class Rocker extends Component {
    @property(Node)
    private stick: Node = null;

    private touchId: number = null;
    private rockerPos: Vec2 = new Vec2();
    private MAX_DISTANCE: number;
    private allowResetKeyCode: KeyCode[] = [KeyCode.KEY_W, KeyCode.KEY_S, KeyCode.KEY_A, KeyCode.KEY_D];

    start() {
        this.node.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
        this.node.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        this.node.on(Node.EventType.TOUCH_END, this.onReset, this);
        this.node.on(Node.EventType.TOUCH_CANCEL, this.onReset, this);

        input.on(Input.EventType.KEY_DOWN, this.onKeyDown, this);
        input.on(Input.EventType.KEY_UP, this.onKeyUp, this);

        const pos = this.node.getPosition();
        this.rockerPos.x = pos.x;
        this.rockerPos.y = pos.y;
        this.MAX_DISTANCE = this.node.getComponent(UITransform).contentSize.width / 2;
    }

    onKeyDown(e: EventKeyboard) {
        switch (e.keyCode) {
            case KeyCode.KEY_W:
                this.calcRockerData(0, this.MAX_DISTANCE);
                break;
            case KeyCode.KEY_S:
                this.calcRockerData(0, -this.MAX_DISTANCE);
                break;
            case KeyCode.KEY_D:
                this.calcRockerData(this.MAX_DISTANCE, 0);
                break;
            case KeyCode.KEY_A:
                this.calcRockerData(-this.MAX_DISTANCE, 0);
                break;
        }
    }

    onKeyUp(e: EventKeyboard) {
        if (this.allowResetKeyCode.includes(e.keyCode)) {
            this.onReset();
        }
    }

    onTouchStart(e: EventTouch) {
        this.touchId = e.getID();
    }

    onTouchMove(e: EventTouch) {
        if (e.touch.getID() !== this.touchId) return;

        let { x, y } = e.getUILocation().subtract(this.rockerPos);
        this.calcRockerData(x, y);
    }

    onReset() {
        this.touchId = null;
        this.stick.setPosition(0, 0);
        event.emit("rocker", { action: "reset", angle: 0, distance: 0 });
    }

    calcRockerData(x, y) {
        let distance = Number(Math.sqrt(x * x + y * y).toFixed(2));
        let angle = Number(((180 * Math.atan2(y, x)) / Math.PI).toFixed(2));

        if (distance > this.MAX_DISTANCE) {
            distance = this.MAX_DISTANCE / distance;
            x *= distance;
            y *= distance;
            distance = this.MAX_DISTANCE;
        }

        distance = Number((distance / this.MAX_DISTANCE).toFixed(2));

        this.stick.setPosition(x, y);
        event.emit("rocker", { action: "move", angle, distance });
    }
}
